home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / povray.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-18  |  49.4 KB  |  2,346 lines  |  [TEXT/MPS ]

  1. /****************************************************************************
  2. *                povray.c
  3. *
  4. *  This module contains the entry routine for the raytracer and the code to
  5. *  parse the parameters on the command line.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include <ctype.h>
  26. #include <time.h>     /* BP */
  27. #include "frame.h"    /* common to ALL modules in this program */
  28. #include "povproto.h"
  29. #include "bezier.h"
  30. #include "blob.h"
  31. #include "bbox.h"
  32. #include "cones.h"
  33. #include "csg.h"
  34. #include "discs.h"
  35. #include "express.h"
  36. #include "fractal.h"
  37. #include "hfield.h"
  38. #include "lathe.h"
  39. #include "lighting.h"
  40. #include "mem.h"
  41. #include "mesh.h"
  42. #include "polysolv.h"
  43. #include "objects.h"
  44. #include "octree.h"
  45. #include "parse.h"
  46. #include "pigment.h"
  47. #include "point.h"
  48. #include "poly.h"
  49. #include "polygon.h"
  50. #include "povray.h"
  51. #include "optin.h"
  52. #include "optout.h"
  53. #include "quadrics.h"
  54. #include "pgm.h"
  55. #include "png_pov.h"
  56. #include "ppm.h"
  57. #include "prism.h"
  58. #include "radiosit.h"
  59. #include "render.h"
  60. #include "sor.h"
  61. #include "spheres.h"
  62. #include "super.h"
  63. #include "targa.h"
  64. #include "texture.h"
  65. #include "tokenize.h"
  66. #include "torus.h"
  67. #include "triangle.h"
  68. #include "truetype.h"
  69. #include "userio.h"     /*Error,Warning,Init_Text_Streams*/
  70. #include "lbuffer.h"
  71. #include "vbuffer.h"
  72.  
  73.  
  74. /*****************************************************************************
  75. * Local preprocessor defines
  76. ******************************************************************************/
  77.  
  78. /* Flags for the variable store. */
  79.  
  80. #define STORE   1
  81. #define RESTORE 2
  82.  
  83.  
  84.  
  85. /*****************************************************************************
  86. * Local typedefs
  87. ******************************************************************************/
  88.  
  89.  
  90.  
  91. /*****************************************************************************
  92. * Local variables
  93. ******************************************************************************/
  94.  
  95. /* The frame. */
  96.  
  97. FRAME Frame;
  98.  
  99. /* Options and display stuff. */
  100.  
  101. char Color_Bits;
  102.  
  103. int Display_Started;
  104.  
  105. int Abort_Test_Every;
  106.  
  107. int Experimental_Flag;
  108.  
  109. /* Current stage of the program. */
  110.  
  111. int Stage;
  112.  
  113. /* Flag if -h option will show help screens. */
  114.  
  115. int Help_Available;
  116.  
  117. /* File and parsing stuff. */
  118.  
  119. Opts opts;
  120. COUNTER stats[MaxStat];
  121. COUNTER totalstats[MaxStat];
  122.  
  123. int Num_Echo_Lines;      /* May make user setable later - CEY*/
  124. int Echo_Line_Length;    /* May make user setable later - CEY*/
  125.  
  126. int Number_Of_Files;
  127.  
  128. FILE *stat_file;
  129. FILE_HANDLE *Output_File_Handle;
  130.  
  131. char Actual_Output_Name[FILE_NAME_LENGTH];
  132.  
  133. /* Timing stuff .*/
  134.  
  135. time_t tstart, tstop;
  136. DBL tparse, trender, tparse_total, trender_total;
  137.  
  138. /* Variable used by vector macros. */
  139.  
  140. DBL VTemp;
  141.  
  142. volatile int Stop_Flag;
  143.  
  144. /* Flag if close_all() was already called. */
  145. static int closed_flag;
  146.  
  147. int pre_init_flag=0;
  148.  
  149. char *Option_String_Ptr;      
  150.  
  151. /*****************************************************************************
  152. * Static functions
  153. ******************************************************************************/
  154.  
  155. static void init_vars PARAMS((void));
  156. static void destroy_libraries PARAMS((void));
  157. static void fix_up_rendering_window PARAMS((void));
  158. static void fix_up_animation_values PARAMS((void));
  159. static void fix_up_scene_name PARAMS((void));
  160. static void set_output_file_handle PARAMS((void));
  161. static void setup_output_file_name PARAMS((void));
  162. static void open_output_file PARAMS((void));
  163. static void FrameRender PARAMS((void));
  164. static void init_statistics PARAMS((COUNTER *));
  165. static void sum_statistics PARAMS((COUNTER *, COUNTER *));
  166. static void variable_store PARAMS((int Flag));
  167. static int Has_Extension PARAMS((char *name));
  168. static unsigned closest_power_of_2 PARAMS((unsigned theNumber));
  169. static void init_shellouts PARAMS((void));
  170. static void destroy_shellouts PARAMS((void));
  171.  
  172.  
  173. /*****************************************************************************
  174. *
  175. * FUNCTION
  176. *
  177. *   main
  178. *
  179. * INPUT
  180. *   
  181. * OUTPUT
  182. *   
  183. * RETURNS
  184. *
  185. * AUTHOR
  186. *
  187. *   POV-Ray Team
  188. *   
  189. * DESCRIPTION
  190. *
  191. *   -
  192. *
  193. * CHANGES
  194. *
  195. *   -
  196. *
  197. ******************************************************************************/
  198.  
  199.  
  200. #ifdef NOCMDLINE    /* a main() by any other name... */
  201. #ifdef ALTMAIN
  202.   MAIN_RETURN_TYPE alt_main()
  203. #else
  204.   MAIN_RETURN_TYPE main()
  205. #endif
  206. #else
  207. #ifdef ALTMAIN
  208.   MAIN_RETURN_TYPE alt_main(argc, argv)
  209. #else
  210.   MAIN_RETURN_TYPE main(argc, argv)
  211. #endif
  212. int argc;
  213. char **argv;
  214. #endif            /* ...would be a lot less hassle!! :-) AAC */
  215. {
  216.   register int i;
  217.   int Diff_Frame;
  218.   DBL Diff_Clock;
  219.   SHELLRET Pre_Scene_Result, Frame_Result;
  220.  
  221.   /* Attention all ALTMAIN people! See comments attached to this function*/
  222.   pre_init_povray();
  223.  
  224.   /* Startup povray. */
  225.   Stage = STAGE_STARTUP;
  226.   STARTUP_POVRAY
  227.  
  228.   /* Print banner and credit info. */
  229.   Stage = STAGE_BANNER;
  230.   PRINT_CREDITS
  231.   PRINT_OTHER_CREDITS
  232.  
  233. #ifndef NOCMDLINE
  234.   /* Print help screens. */
  235.  
  236.   if (argc == 1)
  237.   {
  238.     Print_Help_Screens();
  239.   }
  240. #endif
  241.  
  242.   /* Initialize variables. */
  243.   init_vars();
  244.  
  245.   Stage = STAGE_ENVIRONMENT;
  246.  
  247.   READ_ENV_VAR
  248.  
  249.   Stage = STAGE_INI_FILE;
  250.  
  251.   /* Read parameters from POVRAY.INI */
  252.   PROCESS_POVRAY_INI
  253.  
  254. #ifndef NOCMDLINE
  255.   /* Parse the command line parameters */
  256.  
  257.   Stage = STAGE_COMMAND_LINE;
  258.  
  259.   Help_Available = (argc == 2);
  260.  
  261.   for (i = 1 ; i < argc ; i++ )
  262.   {
  263.     parse_option_line(argv[i]);
  264.   }
  265. #endif
  266.  
  267.   /* Strip path and extension off input name to create scene name */
  268.   fix_up_scene_name ();
  269.   
  270.   /* Redirect text streams [SCD 2/95] */
  271.   Open_Text_Streams();
  272.  
  273.   /* Write .INI file [SCD 2/95] */
  274.   Write_INI_File();
  275.   
  276.   ALT_WRITE_INI_FILE
  277.  
  278.   /* Make sure clock is okay, validate animation parameters */
  279.   fix_up_animation_values();
  280.  
  281.   /* Fix-up rendering window values if necessary. */
  282.   fix_up_rendering_window();
  283.   
  284.   /* Set output file handle for options screen. */
  285.   set_output_file_handle();
  286.  
  287.   /* Print options used. */
  288.   Print_Options();
  289.   
  290.   /* BEGIN SECTION */
  291.   /* VARIOUS INITIALIZATION THAT ONLY NEEDS TO BE DONE 1/EXECUTION */
  292.  
  293.   /* Set up noise-tables. */
  294.   Initialize_Noise();
  295.   
  296.   Diff_Clock = opts.FrameSeq.FinalClock - opts.FrameSeq.InitialClock;
  297.  
  298.   if (opts.Options & CYCLIC_ANIMATION)
  299.   {
  300.     Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1;
  301.   }
  302.   else
  303.   {
  304.     Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame;
  305.   }
  306.   
  307.   /* END SECTION */
  308.  
  309.   /* Execute the first shell-out command */
  310.   Pre_Scene_Result=POV_SHELLOUT(PRE_SCENE_SHL);
  311.  
  312.   /* Loop over each frame */
  313.   
  314.   if (Pre_Scene_Result != ALL_SKIP_RET)
  315.   {
  316.      if (Pre_Scene_Result != SKIP_ONCE_RET)
  317.      {
  318.        for (opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame,
  319.             opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
  320.  
  321.             opts.FrameSeq.FrameNumber <= opts.FrameSeq.FinalFrame;
  322.  
  323.             opts.FrameSeq.FrameNumber++,
  324.             opts.FrameSeq.Clock_Value += ((Diff_Frame==0)?1:Diff_Clock/Diff_Frame))
  325.        {
  326.          setup_output_file_name();
  327.  
  328.          /* Execute a shell-out command before tracing */
  329.  
  330.          Frame_Result=POV_SHELLOUT(PRE_FRAME_SHL);
  331.            
  332.          if (Frame_Result == ALL_SKIP_RET)
  333.          {
  334.            break;
  335.          }
  336.  
  337.          if (Frame_Result != SKIP_ONCE_RET)
  338.          {
  339.            FrameRender();
  340.  
  341.            /* Execute a shell-out command after tracing */
  342.  
  343.            Frame_Result = POV_SHELLOUT(POST_FRAME_SHL);
  344.            
  345.            if ((Frame_Result==SKIP_ONCE_RET) || (Frame_Result==ALL_SKIP_RET))
  346.            {
  347.              break;
  348.            }
  349.          }
  350.        }
  351.  
  352.        /* Print total stats ... */
  353.  
  354.        if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  355.        {
  356.          Statistics("\nTotal Statistics");
  357.     
  358.          opts.FrameSeq.FrameNumber--;
  359.  
  360.          PRINT_STATS(totalstats);
  361.     
  362.          opts.FrameSeq.FrameNumber++;
  363.        }
  364.      }
  365.  
  366.      /* Execute the final shell-out command */
  367.  
  368.      POV_SHELLOUT(POST_SCENE_SHL);
  369.   }
  370.  
  371.   /* And finish. */
  372.  
  373.   Terminate_POV(0);
  374.  
  375.   MAIN_RETURN_STATEMENT
  376. } /* main */
  377.  
  378.  
  379. /*****************************************************************************
  380. *
  381. * FUNCTION
  382. *
  383. *   FrameRender
  384. *
  385. * INPUT
  386. *   
  387. * OUTPUT
  388. *   
  389. * RETURNS
  390. *   
  391. * AUTHOR
  392. *
  393. *   POV-Ray Team
  394. *   
  395. * DESCRIPTION
  396. *
  397. *   Do all that is necessary for rendering a single frame, including parsing
  398. *
  399. * CHANGES
  400. *
  401. *   Feb 1996: Make sure we are displaying when doing a mosaic preview [AED]
  402. *
  403. ******************************************************************************/
  404.  
  405. static void FrameRender()
  406. {
  407.   unsigned long hours, minutes;
  408.   DBL seconds, t_total;
  409.  
  410.   /* Store start time for parse. */
  411.   START_TIME
  412.  
  413.   /* Parse the scene file. */
  414.   Status_Info("\n\nParsing...");
  415.   
  416.   opts.Do_Stats=FALSE;
  417.  
  418.   Init_Random_Generators();
  419.  
  420.   Parse();
  421.  
  422.   Destroy_Random_Generators();
  423.  
  424.   opts.Do_Stats=TRUE;
  425.  
  426.   if (opts.Options & RADIOSITY)
  427.   {
  428.      Experimental_Flag |= EF_RADIOS;
  429.   }
  430.  
  431.   if (Experimental_Flag)
  432.   {
  433.     Warning(0.0,"Warning: This rendering uses the following experimental features:\n");
  434.     if (Experimental_Flag & EF_RADIOS) 
  435.     {
  436.        Warning(0.0," radiosity");
  437.     }
  438.     if (Experimental_Flag & EF_HALOS)
  439.     {
  440.        Warning(0.0," halos");
  441.     }
  442.     if (Experimental_Flag & EF_ATMOS)
  443.     {
  444.        Warning(0.0," atmosphere");
  445.     }
  446.     Warning(0.0,".\nThe design and implementation of these features is likely to\n");
  447.     Warning(0.0,"change in future versions of POV-Ray.  Full backward compatibility\n");
  448.     Warning(0.0,"with the current implementation is NOT guaranteed.\n");
  449.   }
  450.   
  451.   Experimental_Flag=0;
  452.  
  453.   /* Switch off standard anti-aliasing. */
  454.  
  455.   if ((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
  456.   {
  457.     opts.Options &= ~ANTIALIAS;
  458.  
  459.     Warning(0.0, "Focal blur is used. Standard antialiasing is switched off.\n");
  460.   }
  461.  
  462.   /* Create the bounding box hierarchy. */
  463.  
  464.   Stage = STAGE_SLAB_BUILDING;
  465.  
  466.   if (opts.Use_Slabs)
  467.   {
  468.     Status_Info("\nCreating bounding slabs.");
  469.   }
  470.  
  471.   /* Init module specific stuff. */
  472.   Initialize_Atmosphere_Code();
  473.   Initialize_BBox_Code();
  474.   Initialize_Lighting_Code();
  475.   Initialize_Mesh_Code();
  476.   Initialize_VLBuffer_Code();
  477.   Initialize_Radiosity_Code();
  478.  
  479.   /* Always call this to print number of objects. */
  480.   Build_Bounding_Slabs(&Root_Object);
  481.  
  482.   /* Create the vista buffer. */
  483.   Build_Vista_Buffer();
  484.  
  485.   /* Create the light buffers. */
  486.   Build_Light_Buffers();
  487.  
  488.   /* Create blob queue. */
  489.   Init_Blob_Queue();
  490.  
  491.   /* Save variable values. */
  492.   variable_store(STORE);
  493.  
  494.   /* Open output file and if we are continuing an interrupted trace,
  495.    * read in the previous file settings and any data there.  This has to
  496.    * be done before any image-size related allocations, since the settings
  497.    * in a resumed file take precedence over that specified by the user. [AED]
  498.    */
  499.   open_output_file();
  500.  
  501.   /* Start the display. */
  502.   if (opts.Options & DISPLAY)
  503.   {
  504.     Status_Info ("\nDisplaying...");
  505.  
  506.     POV_DISPLAY_INIT(Frame.Screen_Width, Frame.Screen_Height);
  507.  
  508.     Display_Started = TRUE;
  509.  
  510.     /* Display vista tree. */
  511.     Draw_Vista_Buffer();
  512.   }
  513.  
  514.   /* Get things ready for ray tracing (misc init, mem alloc) */
  515.   Initialize_Renderer();
  516.  
  517.   /* This had to be taken out of open_output_file() because we don't have
  518.    * the final image size until the output file has been opened, so we can't
  519.    * initialize the display until we know this, which in turn means we can't
  520.    * read the rendered part before the display is initialized. [AED]
  521.    */
  522.   if ((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
  523.   {
  524.     Read_Rendered_Part(Actual_Output_Name);
  525.  
  526.     if (opts.Last_Line > Frame.Screen_Height)
  527.       opts.Last_Line = Frame.Screen_Height;
  528.  
  529.     if (opts.Last_Column > Frame.Screen_Width)
  530.       opts.Last_Column = Frame.Screen_Width;
  531.  
  532.   }
  533.  
  534.   /* Get parsing time. */
  535.   STOP_TIME
  536.   tparse = TIME_ELAPSED
  537.  
  538.   /* Get total parsing time. */
  539.   tparse_total += tparse;
  540.  
  541.   /* Store start time for trace. */
  542.   START_TIME
  543.  
  544.   if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  545.   {
  546.     t_total=tparse_total+trender_total;
  547.     SPLIT_TIME(t_total,&hours,&minutes,&seconds);
  548.     Render_Info("\n %02ld:%02ld:%02.0f so far, ",hours,minutes,seconds);
  549.     Render_Info("Rendering frame %d, going to %d.",
  550.         opts.FrameSeq.FrameNumber, opts.FrameSeq.FinalFrame);
  551.   }
  552.   /* Start tracing. */
  553.   Stage = STAGE_RENDERING;
  554.  
  555.   POV_PRE_RENDER
  556.  
  557.   Status_Info ("\nRendering...\r");
  558.  
  559.   /* Macro for setting up any special FP options */
  560.   CONFIG_MATH
  561.  
  562.   /* Ok, go for it - trace the picture. */
  563.  
  564.   /* If radiosity preview has been done, we are continuing a trace, so it
  565.    * is important NOT to do the preview, even if the user requests it, as it
  566.    * will cause discontinuities in radiosity shading by (probably) calculating
  567.    * a few more radiosity values.
  568.    */
  569.   if ( !opts.Radiosity_Preview_Done )
  570.   {
  571.     if ( opts.Options & RADIOSITY )
  572.     {
  573.       /* Note that radiosity REQUIRES a mosaic preview prior to main scan */
  574.  
  575.       Start_Tracing_Mosaic_Smooth(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
  576.     }
  577.     else
  578.     {
  579.       if (opts.Options & PREVIEW && opts.Options & DISPLAY)
  580.       {
  581.         Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
  582.       }
  583.     }
  584.   }
  585.  
  586.   switch (opts.Tracing_Method)
  587.   {
  588.     case 2 :
  589.  
  590.       Start_Adaptive_Tracing();
  591.  
  592.       break;
  593.  
  594.     case 1 :
  595.     default:
  596.  
  597.       Start_Non_Adaptive_Tracing();
  598.   }
  599.  
  600.   /* We're done. */
  601.  
  602.   /* Record time so well spent before file close so it can be in comments  */
  603.   STOP_TIME
  604.   trender = TIME_ELAPSED
  605.  
  606.   /* Close out our file */
  607.   if (Output_File_Handle)
  608.   {
  609.      Close_File(Output_File_Handle);
  610.   }
  611.  
  612.   Stage = STAGE_SHUTDOWN;
  613.  
  614.   POV_PRE_SHUTDOWN
  615.  
  616.   /* DESTROY lots of stuff */
  617.   Deinitialize_Atmosphere_Code();
  618.   Deinitialize_BBox_Code();
  619.   Deinitialize_Lighting_Code();
  620.   Deinitialize_Mesh_Code();
  621.   Deinitialize_VLBuffer_Code();
  622.   Deinitialize_Radiosity_Code();
  623.   Destroy_Blob_Queue();
  624.   Destroy_Light_Buffers();
  625.   Destroy_Vista_Buffer();
  626.   Destroy_Bounding_Slabs();
  627.   Destroy_Frame();
  628.   Terminate_Renderer();
  629.   FreeFontInfo();
  630.   Free_Iteration_Stack();
  631.  
  632.   POV_POST_SHUTDOWN
  633.  
  634.   /* Get total render time. */
  635.   trender_total += trender;
  636.  
  637.   POV_DISPLAY_FINISHED
  638.  
  639.   if ((opts.Options & DISPLAY) && Display_Started)
  640.   {
  641.     POV_DISPLAY_CLOSE
  642.  
  643.     Display_Started = FALSE;
  644.   }
  645.  
  646.   if (opts.histogram_on)
  647.     write_histogram (opts.Histogram_File_Name) ;
  648.  
  649.   Status_Info("\nDone Tracing");
  650.  
  651.   /* Print stats ... */
  652.   PRINT_STATS(stats);
  653.  
  654.   if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  655.   {
  656.     /* Add them up */
  657.     sum_statistics(totalstats, stats);
  658.  
  659.     /* ... and then clear them for the next frame */
  660.     init_statistics(stats);
  661.   }
  662.  
  663.   /* Restore variable values. */
  664.   variable_store(RESTORE);
  665.  
  666. }
  667.  
  668.  
  669.  
  670. /*****************************************************************************
  671. *
  672. * FUNCTION
  673. *
  674. *   fix_up_rendering_window
  675. *
  676. * INPUT
  677. *   
  678. * OUTPUT
  679. *   
  680. * RETURNS
  681. *   
  682. * AUTHOR
  683. *
  684. *   POV-Ray Team
  685. *   
  686. * DESCRIPTION
  687. *
  688. *   Fix wrong window and mosaic preview values.
  689. *
  690. * CHANGES
  691. *
  692. *   -
  693. *
  694. ******************************************************************************/
  695.  
  696. static void fix_up_rendering_window()
  697. {
  698.   int temp;
  699.   
  700.   if (opts.First_Column_Percent > 0.0)
  701.     opts.First_Column = (int) (Frame.Screen_Width * opts.First_Column_Percent);
  702.  
  703.   if (opts.First_Line_Percent > 0.0)
  704.     opts.First_Line = (int) (Frame.Screen_Height * opts.First_Line_Percent);
  705.  
  706.   /* The decrements are a fudge factor that used to be in OPTIN.C
  707.    * but it messed up Write_INI_File so its moved here.
  708.    */
  709.  
  710.   if (opts.First_Column <= 0)
  711.     opts.First_Column = 0;
  712.   else
  713.     opts.First_Column--;
  714.  
  715.   if (opts.First_Line <= 0)
  716.     opts.First_Line = 0;
  717.   else
  718.     opts.First_Line--;
  719.   
  720.   if ((opts.Last_Column == -1) && (opts.Last_Column_Percent <= 1.0))
  721.     opts.Last_Column = (int) (Frame.Screen_Width * opts.Last_Column_Percent);
  722.  
  723.   if ((opts.Last_Line == -1) && (opts.Last_Line_Percent <= 1.0))
  724.     opts.Last_Line = (int) (Frame.Screen_Height * opts.Last_Line_Percent);
  725.  
  726.   if (opts.Last_Line == -1)
  727.     opts.Last_Line = Frame.Screen_Height;
  728.  
  729.   if (opts.Last_Column == -1)
  730.     opts.Last_Column = Frame.Screen_Width;
  731.  
  732.   if (opts.Last_Column < 0 || opts.Last_Column > Frame.Screen_Width)
  733.     opts.Last_Column = Frame.Screen_Width;
  734.  
  735.   if (opts.Last_Line > Frame.Screen_Height)
  736.     opts.Last_Line = Frame.Screen_Height;
  737.  
  738.   /* Fix up Mosaic Preview values */
  739.   opts.PreviewGridSize_Start=max(1,opts.PreviewGridSize_Start);
  740.   opts.PreviewGridSize_End=max(1,opts.PreviewGridSize_End);
  741.  
  742.   if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_Start))!=opts.PreviewGridSize_Start)
  743.   {
  744.      Warning(0.0,"Preview_Start_Size must be a power of 2. Changing to %d.\n",temp);
  745.      opts.PreviewGridSize_Start=temp;
  746.   }
  747.  
  748.   if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_End))!=opts.PreviewGridSize_End)
  749.   {
  750.      Warning(0.0,"Preview_End_Size must be a power of 2. Changing to %d.\n",temp);
  751.      opts.PreviewGridSize_End=temp;
  752.   }
  753.  
  754.   /* End must be less than or equal to start */
  755.   if (opts.PreviewGridSize_End > opts.PreviewGridSize_Start)
  756.     opts.PreviewGridSize_End = opts.PreviewGridSize_Start;
  757.     
  758.   if (opts.PreviewGridSize_Start > 1)
  759.   {
  760.      opts.PreviewGridSize_End=max(opts.PreviewGridSize_End,2);
  761.      opts.Options |= PREVIEW;
  762.   }
  763.   else
  764.   {
  765.      opts.Options &= ~PREVIEW;
  766.   }
  767.  
  768.   /* Set histogram size here so it is available for Print_Options, and
  769.    * make sure that it has an integer number of pixels/bucket. */
  770.   if (opts.histogram_on)
  771.   {
  772.     if (opts.histogram_x == 0 || opts.histogram_x > Frame.Screen_Width)
  773.       opts.histogram_x = Frame.Screen_Width;
  774.     else if (opts.histogram_x < Frame.Screen_Width)
  775.       opts.histogram_x = Frame.Screen_Width / ((Frame.Screen_Width +
  776.                          opts.histogram_x - 1) / opts.histogram_x);
  777.  
  778.     if (opts.histogram_y == 0 || opts.histogram_y > Frame.Screen_Height)
  779.       opts.histogram_y = Frame.Screen_Height;
  780.     else if (opts.histogram_y < Frame.Screen_Height)
  781.       opts.histogram_y = Frame.Screen_Height / ((Frame.Screen_Height +
  782.                          opts.histogram_y - 1) /opts.histogram_y);
  783.   }
  784. }
  785.  
  786. /*****************************************************************************
  787. *
  788. * FUNCTION
  789. *
  790. *   fix_up_animation_values
  791. *
  792. * INPUT
  793. *   
  794. * OUTPUT
  795. *   
  796. * RETURNS
  797. *   
  798. * AUTHOR
  799. *
  800. *   POV-Ray Team
  801. *   
  802. * DESCRIPTION
  803. *
  804. *   Validate animation parameters, compute subset values
  805. *
  806. * CHANGES
  807. *
  808. *   -
  809. *
  810. ******************************************************************************/
  811. static void fix_up_animation_values()
  812. {
  813.   float ClockDiff;
  814.   int FrameDiff;
  815.   int FrameIncr;
  816.   float ClockPerFrameIncr;
  817.   int NumFrames;
  818.  
  819.   if (opts.FrameSeq.FinalFrame != -1)
  820.   {
  821.     opts.FrameSeq.FrameType = FT_MULTIPLE_FRAME;
  822.  
  823.     if (opts.FrameSeq.Clock_Value != 0.0)
  824.     {
  825.        Warning(0.0,"Attempted to set single clock value in multi frame\nanimation. Clock value overridden.\n");
  826.     }
  827.   }
  828.   else
  829.   {
  830.     if (opts.FrameSeq.Clock_Value != 0.0)
  831.     {
  832.        opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
  833.     }
  834.   }
  835.  
  836.   if (opts.FrameSeq.FrameType == FT_SINGLE_FRAME)
  837.   {
  838.     /*
  839.      * These are dummy values that will work for single_frame,
  840.      * even in an animation loop.
  841.      */
  842.  
  843.     opts.FrameSeq.InitialFrame = 0;
  844.     opts.FrameSeq.FinalFrame   = 0;
  845.     opts.FrameSeq.InitialClock = opts.FrameSeq.Clock_Value;
  846.     opts.FrameSeq.FinalClock   = 0.0;
  847.   }
  848.   else
  849.   {
  850.     /* FrameType==FT_MULTIPLE_FRAME */
  851.  
  852.     if(opts.FrameSeq.InitialFrame == -1)
  853.     {
  854.       opts.FrameSeq.InitialFrame = 1;
  855.     }
  856.  
  857.     if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
  858.     {
  859.       Error("Final frame %d is less than Start Frame %d.\n",
  860.             opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
  861.     }
  862.  
  863.     ClockDiff = opts.FrameSeq.FinalClock-opts.FrameSeq.InitialClock;
  864.  
  865.     if (opts.Options & CYCLIC_ANIMATION)
  866.     {
  867.       FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame+1;
  868.     }
  869.     else
  870.     {
  871.       FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame;
  872.     }
  873.  
  874.     ClockPerFrameIncr = (FrameDiff == 0) ? 0 : (ClockDiff/FrameDiff);
  875.  
  876.     /* Calculate width, which is an integer log10 */
  877.  
  878.     NumFrames = opts.FrameSeq.FinalFrame;
  879.  
  880.     opts.FrameSeq.FrameNumWidth = 1;
  881.  
  882.     while (NumFrames >= 10)
  883.     {
  884.       opts.FrameSeq.FrameNumWidth++;
  885.  
  886.       NumFrames = NumFrames / 10;
  887.     }
  888.  
  889.     if (opts.FrameSeq.FrameNumWidth > POV_NAME_MAX-1)
  890.     {
  891.       Error("Can't render %d frames requiring %d chars with %d width filename.\n",
  892.           opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1,
  893.           opts.FrameSeq.FrameNumWidth, POV_NAME_MAX);
  894.     }
  895.  
  896.     /* STARTING FRAME SUBSET */
  897.  
  898.     if (opts.FrameSeq.SubsetStartPercent != DBL_VALUE_UNSET)
  899.     {
  900.       FrameIncr = FrameDiff * opts.FrameSeq.SubsetStartPercent + 0.5; /* w/rounding */
  901.  
  902.       opts.FrameSeq.SubsetStartFrame = opts.FrameSeq.InitialFrame + FrameIncr;
  903.     }
  904.  
  905.     if (opts.FrameSeq.SubsetStartFrame != INT_VALUE_UNSET)
  906.     {
  907.       NumFrames = opts.FrameSeq.SubsetStartFrame - opts.FrameSeq.InitialFrame;
  908.  
  909.       opts.FrameSeq.InitialFrame = opts.FrameSeq.SubsetStartFrame;
  910.       opts.FrameSeq.InitialClock = opts.FrameSeq.InitialClock + NumFrames * ClockPerFrameIncr;
  911.     }
  912.  
  913.     /* ENDING FRAME SUBSET */
  914.  
  915.     if (opts.FrameSeq.SubsetEndPercent != DBL_VALUE_UNSET)
  916.     {
  917.       /*
  918.        * By this time, we have possibly lost InitialFrame, so we calculate
  919.        * it via FinalFrame-FrameDiff
  920.        */
  921.  
  922.       FrameIncr = FrameDiff * opts.FrameSeq.SubsetEndPercent + 0.5; /* w/rounding */
  923.  
  924.       opts.FrameSeq.SubsetEndFrame = (opts.FrameSeq.FinalFrame - FrameDiff) + FrameIncr;
  925.     }
  926.  
  927.     if (opts.FrameSeq.SubsetEndFrame != INT_VALUE_UNSET)
  928.     {
  929.       NumFrames = opts.FrameSeq.FinalFrame - opts.FrameSeq.SubsetEndFrame;
  930.  
  931.       opts.FrameSeq.FinalFrame = opts.FrameSeq.SubsetEndFrame;
  932.       opts.FrameSeq.FinalClock = opts.FrameSeq.FinalClock - NumFrames * ClockPerFrameIncr;
  933.     }
  934.  
  935.     /*
  936.      * Now that we have everything calculated, we check FinalFrame
  937.      * and InitialFrame one more time, in case the subsets messed them up
  938.      */
  939.  
  940.     if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
  941.     {
  942.       Error("Final frame %d is less than Start Frame %d\ndue to bad subset specification.\n",
  943.             opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
  944.     }
  945.   }
  946.  
  947.   /* Needed for pre-render shellout fixup */
  948.  
  949.   opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame;
  950.   opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
  951. }
  952.  
  953. /*****************************************************************************
  954. *
  955. * FUNCTION
  956. *
  957. *   fix_up_scene_name
  958. *
  959. * INPUT
  960. *   
  961. * OUTPUT
  962. *   
  963. * RETURNS
  964. *   
  965. * AUTHOR
  966. *
  967. *   POV-Ray Team
  968. *   
  969. * DESCRIPTION
  970. *
  971. *   Strip path and extention of input file to create scene name
  972. *
  973. * CHANGES
  974. *
  975. ******************************************************************************/
  976.  
  977. static void fix_up_scene_name()
  978. {
  979.   int i, l;
  980.   char temp[FILE_NAME_LENGTH];
  981.   
  982.   if ((l=strlen(opts.Input_File_Name)-1)<1)
  983.   {
  984.      strcpy(opts.Scene_Name,opts.Input_File_Name);
  985.      return;
  986.   }
  987.  
  988.   strcpy(temp,opts.Input_File_Name);
  989.   for (i=l;i>0;i--)
  990.   {
  991.      if (temp[i]==FILENAME_SEPARATOR)
  992.      {
  993.         break;
  994.      }
  995.      if (temp[i]=='.')
  996.      {
  997.         temp[i]=0;
  998.         break;
  999.      }
  1000.   }
  1001.  
  1002.   i=strlen(temp)-1;
  1003.   
  1004.   while ((i>0) && (temp[i]!=FILENAME_SEPARATOR))
  1005.     i--;
  1006.   if (temp[i]==FILENAME_SEPARATOR)
  1007.     i++;
  1008.   strcpy(opts.Scene_Name,&(temp[i]));
  1009. }
  1010.  
  1011. /*****************************************************************************
  1012. *
  1013. * FUNCTION
  1014. *
  1015. *   set_output_file_handle
  1016. *
  1017. * INPUT
  1018. *   
  1019. * OUTPUT
  1020. *   
  1021. * RETURNS
  1022. *   
  1023. * AUTHOR
  1024. *
  1025. *   POV-Ray Team
  1026. *   
  1027. * DESCRIPTION
  1028. *
  1029. *   Set the output file handle according to the file type used.
  1030. *
  1031. * CHANGES
  1032. *
  1033. * Oct 95 - Removed test where the output file handle was only set if
  1034. *          output_to_file was TRUE. The output file handle structure
  1035. *          contains a pointer to read line, which is used by the continue
  1036. *          trace option. If you tried a continue trace with file output
  1037. *          manually turned OFF, then a GPF would occur due to a call to a
  1038. *          NULL function pointer.
  1039. *
  1040. ******************************************************************************/
  1041.  
  1042. static void set_output_file_handle()
  1043. {
  1044.   char *def_ext = NULL;
  1045.   char temp[FILE_NAME_LENGTH];
  1046.  
  1047.     switch (opts.OutputFormat)
  1048.     {
  1049.       case '\0':
  1050.       case 's' :
  1051.       case 'S' : Output_File_Handle = GET_SYS_FILE_HANDLE(); def_ext=SYS_DEF_EXT; break;
  1052.  
  1053.       case 't' :
  1054.       case 'T' :
  1055.       case 'c' :
  1056.       case 'C' : Output_File_Handle = Get_Targa_File_Handle(); def_ext=".tga"; break;
  1057.  
  1058.       case 'p' :
  1059.       case 'P' : Output_File_Handle = Get_PPM_File_Handle(); def_ext=".ppm"; break;
  1060.  
  1061.       case 'n' :
  1062.       case 'N' : Output_File_Handle = Get_Png_File_Handle(); def_ext=".png"; break;
  1063.       
  1064.       case 'd' :
  1065.       case 'D' : Error ("Dump format no longer supported.\n"); break;
  1066.       case 'r' :
  1067.       case 'R' : Error ("Raw format no longer supported.\n"); break;
  1068.  
  1069.       default  : Error ("Unrecognized output file format %c.\n",
  1070.                         opts.OutputFormat);
  1071.     }
  1072.  
  1073.     Output_File_Handle->file_type = IMAGE_FTYPE;
  1074.  
  1075.     strcpy(temp,opts.Output_File_Name);
  1076.     
  1077.     POV_SPLIT_PATH(temp,opts.Output_Path,opts.Output_File_Name);
  1078.  
  1079.     if (opts.Output_File_Name[0] == '\0')
  1080.     {
  1081.       sprintf(opts.Output_File_Name, "%s%s",opts.Scene_Name,def_ext);
  1082.     }
  1083.     else if (!(opts.Options & TO_STDOUT))
  1084.     {
  1085.        if (!Has_Extension(opts.Output_File_Name))
  1086.        {
  1087.          strcat(opts.Output_File_Name, def_ext);
  1088.        }
  1089.     }
  1090.     
  1091.     strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
  1092. }
  1093.  
  1094. /*****************************************************************************
  1095. *
  1096. * FUNCTION
  1097. *
  1098. *   setup_output_file_name
  1099. *
  1100. * INPUT
  1101. *   
  1102. * OUTPUT
  1103. *
  1104. * RETURNS
  1105. *   
  1106. * AUTHOR
  1107. *
  1108. *   POV-Ray Team
  1109. *   
  1110. * DESCRIPTION
  1111. *
  1112. *   Determine the file name for this frame.  For an animation, the frame
  1113. *   number is inserted into the file name.
  1114. *
  1115. * CHANGES
  1116. *
  1117. *   Jan-97  [esp]  Added conditional after getcwd, because Metrowerks getcwd
  1118. *                  function appends a path separator on output.
  1119. *
  1120. ******************************************************************************/
  1121. static void setup_output_file_name()
  1122. {
  1123.   char number_string[10];
  1124.   char separator_string[2] = {FILENAME_SEPARATOR, 0} ;
  1125.   char *plast_period;
  1126.   int available_characters;
  1127.   int ilast_period;
  1128.   int fname_chars;
  1129.  
  1130.   /* This will create the real name for the file */
  1131.   if(opts.FrameSeq.FrameType!=FT_MULTIPLE_FRAME ||
  1132.      opts.Options & TO_STDOUT)
  1133.   {
  1134.     strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
  1135.   }
  1136.   else
  1137.   {
  1138.     /*
  1139.      * This is the maximum number of characters that can be used of the
  1140.      * original filename.  This will ensure that enough space is available
  1141.      * for the frame number in the filename
  1142.      */
  1143.  
  1144.     available_characters = POV_NAME_MAX-opts.FrameSeq.FrameNumWidth;
  1145.  
  1146.     plast_period = strrchr(opts.Output_File_Name, '.');
  1147.  
  1148.     if (plast_period == NULL)
  1149.     {
  1150.       Error("Illegal file name %s -- no extension.\n", opts.Output_File_Name);
  1151.     }
  1152.  
  1153.     ilast_period = plast_period - opts.Output_File_Name;
  1154.  
  1155.     fname_chars = ilast_period;
  1156.  
  1157.     if (fname_chars > available_characters)
  1158.     {
  1159.       /* Only give the warning once */
  1160.  
  1161.       if (opts.FrameSeq.FrameNumber == opts.FrameSeq.InitialFrame)
  1162.       {
  1163.         Warning(0.0, "Need to cut the output filename by %d characters.\n",
  1164.                 ilast_period - available_characters);
  1165.       }
  1166.  
  1167.       fname_chars = available_characters;
  1168.     }
  1169.  
  1170.     /* Perform actual generation of filename */
  1171.  
  1172.     strncpy(opts.Output_Numbered_Name, opts.Output_File_Name, (unsigned)fname_chars);
  1173.  
  1174.     /* strncpy doesn't terminate if strlen(opts.Output_File_Name)<fname_chars */
  1175.  
  1176.     opts.Output_Numbered_Name[fname_chars]='\0';
  1177.  
  1178.     sprintf(number_string, "%0*d", opts.FrameSeq.FrameNumWidth, opts.FrameSeq.FrameNumber);
  1179.  
  1180.     strcat(opts.Output_Numbered_Name, number_string);
  1181.  
  1182.     strcat(opts.Output_Numbered_Name, &opts.Output_File_Name[ilast_period]);
  1183.   }
  1184.  
  1185.   if (strlen (opts.Output_Path) == 0)
  1186.   {
  1187.     getcwd (opts.Output_Path, sizeof (opts.Output_Path) - 1) ;
  1188.     /* on some systems (MacOS) getcwd adds the path separator on the end */
  1189.     /* so only add it if it isn't already there...  [esp]                */
  1190.     if (opts.Output_Path[strlen(opts.Output_Path)-1] != FILENAME_SEPARATOR)
  1191.         strcat (opts.Output_Path, separator_string) ;
  1192.   }
  1193.   strncpy (Actual_Output_Name,opts.Output_Path, sizeof (Actual_Output_Name));
  1194.   strncat (Actual_Output_Name,opts.Output_Numbered_Name, sizeof (Actual_Output_Name));
  1195. /*
  1196. Debug_Info("P='%s',O='%s',A='%s',N='%s'\n",opts.Output_Path,
  1197.   opts.Output_Numbered_Name, Actual_Output_Name,opts.Output_Numbered_Name);
  1198. */
  1199. }
  1200.  
  1201.  
  1202. /*****************************************************************************
  1203. *
  1204. * FUNCTION
  1205. *
  1206. *   open_output_file
  1207. *
  1208. * INPUT
  1209. *   
  1210. * OUTPUT
  1211. *   
  1212. * RETURNS
  1213. *   
  1214. * AUTHOR
  1215. *
  1216. *   POV-Ray Team
  1217. *   
  1218. * DESCRIPTION
  1219. *
  1220. *   Open file and read in previous image if continued trace is on.
  1221. *
  1222. *   GOTCHA : This saves a POINTER to the file name, so the file
  1223. *            name must exist over the entire life/use of the file
  1224. *
  1225. * CHANGES
  1226. *
  1227. *   -
  1228. *
  1229. ******************************************************************************/
  1230.  
  1231. static void open_output_file()
  1232. {
  1233.   int Buffer_Size;
  1234.   
  1235.   if (opts.Options & DISKWRITE)
  1236.   {
  1237.     Stage = STAGE_FILE_INIT;
  1238.     
  1239.     if (opts.Options & BUFFERED_OUTPUT)
  1240.     {
  1241.        Buffer_Size=opts.File_Buffer_Size;
  1242.     }
  1243.     else
  1244.     {
  1245.        Buffer_Size=0;
  1246.     }
  1247.  
  1248.     if (opts.Options & CONTINUE_TRACE)
  1249.     {
  1250.       Stage = STAGE_CONTINUING;
  1251.  
  1252.       if (Open_File(Output_File_Handle, Actual_Output_Name,
  1253.             &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1254.             READ_MODE) != 1)
  1255.       {
  1256.         Close_File(Output_File_Handle);
  1257.  
  1258.         Warning (0.0,"Error opening continue trace output file.\n");
  1259.  
  1260.         Warning (0.0,"Opening new output file %s.\n",Actual_Output_Name);
  1261.  
  1262.         /* Turn off continue trace */
  1263.  
  1264.         opts.Options &= ~CONTINUE_TRACE;
  1265.  
  1266.         if (Open_File(Output_File_Handle, Actual_Output_Name,
  1267.               &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1268.               WRITE_MODE) != 1)
  1269.         {
  1270.           Error ("Error opening output file.");
  1271.         }
  1272.       }
  1273.     }
  1274.     else
  1275.     {
  1276.       if (Open_File(Output_File_Handle, Actual_Output_Name,
  1277.             &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1278.             WRITE_MODE) != 1)
  1279.       {
  1280.         Error ("Error opening output file.");
  1281.       }
  1282.     }
  1283.   }
  1284. }
  1285.  
  1286.  
  1287. /*****************************************************************************
  1288. *
  1289. * FUNCTION
  1290. *
  1291. *   init_vars
  1292. *
  1293. * INPUT
  1294. *   
  1295. * OUTPUT
  1296. *   
  1297. * RETURNS
  1298. *   
  1299. * AUTHOR
  1300. *
  1301. *   POV-Ray Team
  1302. *   
  1303. * DESCRIPTION
  1304. *
  1305. *   Initialize all global variables.
  1306. *
  1307. * CHANGES
  1308. *
  1309. *   -
  1310. *
  1311. ******************************************************************************/
  1312.  
  1313. static void init_vars()
  1314. {
  1315.   Stage=STAGE_INIT;
  1316.   opts.Abort_Test_Counter = Abort_Test_Every ;
  1317.   Abort_Test_Every = 1;
  1318.   opts.AntialiasDepth = 3;
  1319.   opts.Antialias_Threshold = 0.3;
  1320.   opts.BBox_Threshold = 25;
  1321.   Color_Bits = 8;
  1322.   opts.DisplayFormat = '0';
  1323.   Display_Started = FALSE;
  1324.   opts.File_Buffer_Size = 0;
  1325.   opts.First_Column = 0;
  1326.   opts.First_Column_Percent = 0.0;
  1327.   opts.First_Line = 0;
  1328.   opts.First_Line_Percent = 0.0;
  1329.   Frame.Screen_Height = 100;
  1330.   Frame.Screen_Width  = 100;
  1331.   Root_Object = NULL;
  1332.   free_istack = NULL;
  1333.   opts.JitterScale = 1.0;
  1334.   opts.Language_Version = 3.0;
  1335.   opts.Last_Column = -1;
  1336.   opts.Last_Column_Percent = 1.0;
  1337.   opts.Last_Line = -1;
  1338.   opts.Last_Line_Percent = 1.0;
  1339.   opts.PreviewGridSize_Start = 1;
  1340.   opts.PreviewGridSize_End   = 1;
  1341.   opts.Library_Paths[0] = NULL;
  1342.   opts.Library_Path_Index = 0;
  1343.   Max_Intersections = 64; /*128*/
  1344.   Max_Symbols = Max_Constants = 1024;
  1345.   Number_Of_Files = 0;
  1346.   Number_of_istacks = 0;
  1347.  
  1348.   opts.Options = USE_VISTA_BUFFER + USE_LIGHT_BUFFER + JITTER +
  1349.                  DISKWRITE + REMOVE_BOUNDS;
  1350.   opts.OutputFormat = DEFAULT_OUTPUT_FORMAT;
  1351.   opts.OutputQuality = 8;
  1352.   Output_File_Handle = NULL;
  1353.   opts.Output_Numbered_Name[0]='\0';
  1354.   opts.Output_File_Name[0]='\0';
  1355.   opts.Output_Path[0]='\0';
  1356.   opts.PaletteOption = '3';
  1357.   opts.Quality = 9;
  1358.   opts.Quality_Flags = QUALITY_9;
  1359.   opts.DisplayGamma = DEFAULT_DISPLAY_GAMMA;
  1360.  
  1361.   /* 
  1362.    * If DisplayGamma == 2.2, then GammaFactor == .45, which is what we want.
  1363.    */
  1364.   opts.GammaFactor = DEFAULT_ASSUMED_GAMMA/opts.DisplayGamma;
  1365.  
  1366.   opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
  1367.   opts.FrameSeq.Clock_Value = 0.0;
  1368.   opts.FrameSeq.InitialFrame = 1;
  1369.   opts.FrameSeq.InitialClock = 0.0;
  1370.   opts.FrameSeq.FinalFrame = INT_VALUE_UNSET;
  1371.   opts.FrameSeq.FrameNumWidth = 0;
  1372.   opts.FrameSeq.FinalClock = 1.0;
  1373.   opts.FrameSeq.SubsetStartFrame = INT_VALUE_UNSET;
  1374.   opts.FrameSeq.SubsetStartPercent = DBL_VALUE_UNSET;
  1375.   opts.FrameSeq.SubsetEndFrame = INT_VALUE_UNSET;
  1376.   opts.FrameSeq.SubsetEndPercent = DBL_VALUE_UNSET;
  1377.   opts.FrameSeq.Field_Render_Flag = FALSE;
  1378.   opts.FrameSeq.Odd_Field_Flag = FALSE;
  1379.  
  1380.   opts.Radiosity_Brightness = 3.3;
  1381.   opts.Radiosity_Count = 100;
  1382.   opts.Radiosity_Dist_Max = 0.;   /* default calculated in Radiosity_Initialize */
  1383.   opts.Radiosity_Error_Bound = .4;
  1384.   opts.Radiosity_Gray = .5;       /* degree to which gathered light is grayed */
  1385.   opts.Radiosity_Low_Error_Factor = .8;
  1386.   opts.Radiosity_Min_Reuse = .015;
  1387.   opts.Radiosity_Nearest_Count = 6;
  1388.   opts.Radiosity_Recursion_Limit = 1;
  1389.   opts.Radiosity_Quality = 6;     /* Q-flag value for light gathering */
  1390.   opts.Radiosity_File_ReadOnContinue = 1;
  1391.   opts.Radiosity_File_SaveWhileRendering = 1;
  1392.   opts.Radiosity_File_AlwaysReadAtStart = 0;
  1393.   opts.Radiosity_File_KeepOnAbort = 1;
  1394.   opts.Radiosity_File_KeepAlways = 0;
  1395.  
  1396.  
  1397.   init_statistics(stats);
  1398.   init_statistics(totalstats);
  1399.  
  1400.   strcpy (opts.Input_File_Name, "OBJECT.POV");
  1401.   opts.Scene_Name[0]='\0';
  1402.   opts.Ini_Output_File_Name[0]='\0';
  1403.   opts.Use_Slabs=TRUE;
  1404.   Num_Echo_Lines = 5;   /* May make user setable later - CEY*/
  1405.   Echo_Line_Length = 180;   /* May make user setable later - CEY*/
  1406.  
  1407.   closed_flag = FALSE;
  1408.   Stop_Flag = FALSE;
  1409.  
  1410.   trender = trender_total = 0.0;
  1411.   tparse  = tparse_total  = 0.0;
  1412.  
  1413.   histogram_grid = NULL ;
  1414.   opts.histogram_on = FALSE ;
  1415.   opts.histogram_type = NONE ;
  1416.   opts.Histogram_File_Name[0] = '\0';
  1417.   Histogram_File_Handle = NULL ;
  1418.   /*
  1419.    * Note that late initialization of the histogram_x and histogram_y
  1420.    * variables is done in fix_up_rendering_window, if they aren't specified
  1421.    * on the command line.  This is because they are based on the image
  1422.    * dimensions, and we can't be certain that we have this info at the
  1423.    * time we parse the histogram options in optin.c. [AED]
  1424.    */
  1425.   opts.histogram_x = opts.histogram_y = 0 ;
  1426.   max_histogram_value = 0 ;
  1427.  
  1428.   opts.Tracing_Method = 1;
  1429.   Experimental_Flag = 0;
  1430.   Make_Pigment_Entries();
  1431. }
  1432.  
  1433.  
  1434. /*****************************************************************************
  1435. *
  1436. * FUNCTION
  1437. *
  1438. *   init_statistics
  1439. *
  1440. * INPUT
  1441. *   
  1442. * OUTPUT
  1443. *   
  1444. * RETURNS
  1445. *   
  1446. * AUTHOR
  1447. *
  1448. *   POV-Ray Team
  1449. *   
  1450. * DESCRIPTION
  1451. *
  1452. *   Initialize statistics to 0
  1453. *
  1454. * CHANGES
  1455. *
  1456. *   -
  1457. *
  1458. ******************************************************************************/
  1459.  
  1460. static void init_statistics(pstats)
  1461. COUNTER *pstats;
  1462. {
  1463.   int i;
  1464.  
  1465.   for(i=0; i<MaxStat; i++)
  1466.     Init_Counter(pstats[i]);
  1467. }
  1468.  
  1469. /*****************************************************************************
  1470. *
  1471. * FUNCTION
  1472. *
  1473. *   sum_statistics
  1474. *
  1475. * INPUT
  1476. *   
  1477. * OUTPUT
  1478. *   
  1479. * RETURNS
  1480. *   
  1481. * AUTHOR
  1482. *
  1483. *   POV-Ray Team
  1484. *   
  1485. * DESCRIPTION
  1486. *
  1487. *   Add current statistics to total statistics
  1488. *
  1489. * CHANGES
  1490. *
  1491. *   -
  1492. *
  1493. ******************************************************************************/
  1494.  
  1495. static void sum_statistics(ptotalstats, pstats)
  1496. COUNTER *ptotalstats;
  1497. COUNTER *pstats;
  1498. {
  1499.   int i;
  1500.   COUNTER tmp;
  1501.  
  1502.   for(i=0; i<MaxStat; i++)
  1503.   {
  1504.     Add_Counter(tmp,pstats[i],ptotalstats[i]);
  1505.     ptotalstats[i]=tmp;
  1506.   }
  1507. }
  1508.  
  1509.  
  1510. /*****************************************************************************
  1511. *
  1512. * FUNCTION
  1513. *
  1514. *   variable_store
  1515. *
  1516. * INPUT
  1517. *
  1518. *   flag - flag telling wether to store or restore variables.
  1519. *   
  1520. * OUTPUT
  1521. *   
  1522. * RETURNS
  1523. *   
  1524. * AUTHOR
  1525. *
  1526. *   Dieter Bayer
  1527. *   
  1528. * DESCRIPTION
  1529. *
  1530. *   Store or restore variables whose value has to be the same for all
  1531. *   frames of an animation and who are changed during every frame.
  1532. *
  1533. * CHANGES
  1534. *
  1535. *   May 1995 : Creation.
  1536. *
  1537. ******************************************************************************/
  1538.  
  1539. static void variable_store(Flag)
  1540. int Flag;
  1541. {
  1542.   static int STORE_First_Line;
  1543.  
  1544.   switch (Flag)
  1545.   {
  1546.     case STORE:
  1547.  
  1548.       STORE_First_Line = opts.First_Line;
  1549.  
  1550.       break;
  1551.  
  1552.     case RESTORE:
  1553.  
  1554.       opts.First_Line = STORE_First_Line;
  1555.  
  1556.       break;
  1557.  
  1558.     default:
  1559.  
  1560.       Error("Unknown flag in variable_store().\n");
  1561.   }
  1562. }
  1563.  
  1564. /*****************************************************************************
  1565. *
  1566. * FUNCTION
  1567. *
  1568. *   destroy_libraries
  1569. *
  1570. * INPUT
  1571. *   
  1572. * OUTPUT
  1573. *   
  1574. * RETURNS
  1575. *   
  1576. * AUTHOR
  1577. *
  1578. *   POV-Ray Team
  1579. *   
  1580. * DESCRIPTION
  1581. *
  1582. *   Free library path memory.
  1583. *
  1584. * CHANGES
  1585. *
  1586. *   -
  1587. *
  1588. ******************************************************************************/
  1589.  
  1590. static void destroy_libraries()
  1591. {
  1592.   int i;
  1593.  
  1594.   for (i = 0; i < opts.Library_Path_Index; i++)
  1595.   {
  1596.     POV_FREE(opts.Library_Paths[i]);
  1597.     
  1598.     opts.Library_Paths[i] = NULL;
  1599.   }
  1600. }
  1601.  
  1602.  
  1603.  
  1604. /*****************************************************************************
  1605. *
  1606. * FUNCTION
  1607. *
  1608. *   close_all
  1609. *
  1610. * INPUT
  1611. *   
  1612. * OUTPUT
  1613. *   
  1614. * RETURNS
  1615. *   
  1616. * AUTHOR
  1617. *
  1618. *   POV-Ray Team
  1619. *   
  1620. * DESCRIPTION
  1621. *
  1622. *   Close all the stuff that has been opened and free all allocated memory.
  1623. *
  1624. * CHANGES
  1625. *
  1626. *   -
  1627. *
  1628. ******************************************************************************/
  1629.  
  1630. void close_all()
  1631. {
  1632.   /* Only close things once */
  1633.  
  1634.   if (closed_flag)
  1635.   {
  1636.     return;
  1637.   }
  1638.  
  1639.   if (Output_File_Handle != NULL)
  1640.   {
  1641.     Close_File(Output_File_Handle);
  1642.     
  1643.     POV_FREE(Output_File_Handle);
  1644.     
  1645.     Output_File_Handle = NULL;
  1646.   }
  1647.  
  1648.   destroy_shellouts();
  1649.   destroy_libraries();
  1650.   Destroy_Text_Streams();
  1651.   Free_Noise_Tables();
  1652.   Terminate_Renderer();
  1653.   Destroy_Bounding_Slabs();
  1654.   Destroy_Blob_Queue();
  1655.   Destroy_Vista_Buffer();
  1656.   Destroy_Light_Buffers();
  1657.   Destroy_Random_Generators();
  1658.   Deinitialize_Radiosity_Code();
  1659.   Free_Iteration_Stack();
  1660.   destroy_histogram();
  1661.   Deinitialize_Atmosphere_Code();
  1662.   Deinitialize_BBox_Code();
  1663.   Deinitialize_Lighting_Code();
  1664.   Deinitialize_Mesh_Code();
  1665.   Deinitialize_VLBuffer_Code();
  1666.   Destroy_Frame();
  1667.   Destroy_IStacks();
  1668.   FreeFontInfo();
  1669.  
  1670.   if ((opts.Options & DISPLAY) && Display_Started)
  1671.   {
  1672.     POV_DISPLAY_CLOSE
  1673.   }
  1674.  
  1675.   closed_flag = TRUE;
  1676. }
  1677.  
  1678.  
  1679.  
  1680. /*****************************************************************************
  1681. *
  1682. * FUNCTION
  1683. *
  1684. *   POV_Std_Split_Time
  1685. *
  1686. * INPUT
  1687. *
  1688. * OUTPUT
  1689. *   
  1690. * RETURNS
  1691. *   
  1692. * AUTHOR
  1693. *
  1694. *   POV-Ray Team
  1695. *   
  1696. * DESCRIPTION
  1697. *
  1698. *   Split time into hours, minutes and seconds.
  1699. *
  1700. * CHANGES
  1701. *
  1702. *   -
  1703. *
  1704. ******************************************************************************/
  1705.  
  1706. void POV_Std_Split_Time(time_dif, hrs, mins, secs)
  1707. DBL time_dif;
  1708. unsigned long *hrs, *mins;
  1709. DBL *secs;
  1710. {
  1711.   *hrs = (unsigned long)(time_dif / 3600.0);
  1712.  
  1713.   *mins = (unsigned long)((time_dif - (DBL)(*hrs * 3600)) / 60.0);
  1714.  
  1715.   *secs = time_dif - (DBL)(*hrs * 3600 + *mins * 60);
  1716. }
  1717.  
  1718.  
  1719.  
  1720.  
  1721. /*****************************************************************************
  1722. *
  1723. * FUNCTION
  1724. *
  1725. *   pov_stricmp
  1726. *
  1727. * INPUT
  1728. *   
  1729. * OUTPUT
  1730. *   
  1731. * RETURNS
  1732. *   
  1733. * AUTHOR
  1734. *
  1735. *   POV-Ray Team
  1736. *   
  1737. * DESCRIPTION
  1738. *
  1739. *   Since the stricmp function isn't available on all systems, we've
  1740. *   provided a simplified version of it here.
  1741. *
  1742. * CHANGES
  1743. *
  1744. *   -
  1745. *
  1746. ******************************************************************************/
  1747.  
  1748. int pov_stricmp (s1, s2)
  1749. char *s1, *s2;
  1750. {
  1751.   char c1, c2;
  1752.  
  1753.   while ((*s1 != '\0') && (*s2 != '\0'))
  1754.   {
  1755.     c1 = *s1++;
  1756.     c2 = *s2++;
  1757.  
  1758.     c1 = (char)toupper(c1);
  1759.     c2 = (char)toupper(c2);
  1760.  
  1761.     if (c1 < c2)
  1762.     {
  1763.       return(-1);
  1764.     }
  1765.  
  1766.     if (c1 > c2)
  1767.     {
  1768.       return(1);
  1769.     }
  1770.   }
  1771.  
  1772.   if (*s1 == '\0')
  1773.   {
  1774.     if (*s2 == '\0')
  1775.     {
  1776.       return(0);
  1777.     }
  1778.     else
  1779.     {
  1780.       return(-1);
  1781.     }
  1782.   }
  1783.   else
  1784.   {
  1785.     return(1);
  1786.   }
  1787. }
  1788.  
  1789.  
  1790. /*****************************************************************************
  1791. *
  1792. * FUNCTION
  1793. *
  1794. *   Locate_File
  1795. *
  1796. * INPUT
  1797. *   
  1798. * OUTPUT
  1799. *   
  1800. * RETURNS
  1801. *   
  1802. * AUTHOR
  1803. *
  1804. *   POV-Ray Team
  1805. *   
  1806. * DESCRIPTION
  1807. *
  1808. *   Find a file in the search path.
  1809. *
  1810. * CHANGES
  1811. *
  1812. *   Apr 1996: Don't add trailing FILENAME_SEPARATOR if we are immediately
  1813. *             following DRIVE_SEPARATOR because of Amiga probs.  [AED]
  1814. *
  1815. ******************************************************************************/
  1816.  
  1817. FILE *Locate_File (filename, mode, ext1, ext2, err_flag)
  1818. char *filename, *mode, *ext1, *ext2; int err_flag;
  1819. {
  1820.   int i,l1,l2;
  1821.   char pathname[FILE_NAME_LENGTH];
  1822.   char file0[FILE_NAME_LENGTH];
  1823.   char file1[FILE_NAME_LENGTH];
  1824.   char file2[FILE_NAME_LENGTH];
  1825.   FILE *f;
  1826.  
  1827.   if (Has_Extension(filename))
  1828.   {
  1829.      l1=l2=0;
  1830.   }
  1831.   else
  1832.   {
  1833.      if ((l1 = strlen(ext1)) > 0)
  1834.      {
  1835.         strcpy(file1, filename);
  1836.         strcat(file1, ext1);
  1837.      }
  1838.  
  1839.      if ((l2 = strlen(ext2)) > 0)
  1840.      {
  1841.         strcpy(file2, filename);
  1842.         strcat(file2, ext2);
  1843.      }
  1844.   }
  1845.  
  1846.   /* Check the current directory first. */
  1847.   if (l1)
  1848.   {
  1849.      if ((f = fopen(file1, mode)) != NULL)
  1850.      {
  1851.        return(f);
  1852.      }
  1853.   }
  1854.   if (l2)
  1855.   {
  1856.      if ((f = fopen(file2, mode)) != NULL)
  1857.      {
  1858.        return(f);
  1859.      }
  1860.   }
  1861.   if ((f = fopen(filename, mode)) != NULL)
  1862.   {
  1863.      return(f);
  1864.   }
  1865.  
  1866.   for (i = 0; i < opts.Library_Path_Index; i++)
  1867.   {
  1868.     strcpy(file0, opts.Library_Paths[i]);
  1869.     file0[strlen(file0)+1] = '\0';
  1870.     if (file0[strlen(file0) - 1] != DRIVE_SEPARATOR)
  1871.       file0[strlen(file0)] = FILENAME_SEPARATOR;
  1872.  
  1873.     if (l1)
  1874.     {
  1875.        strcpy(pathname, file0);
  1876.        strcat(pathname, file1);
  1877.        if ((f = fopen(pathname, mode)) != NULL)
  1878.        {
  1879.           return(f);
  1880.        }
  1881.     }
  1882.  
  1883.     if (l2)
  1884.     {
  1885.        strcpy(pathname, file0);
  1886.        strcat(pathname, file2);
  1887.        if ((f = fopen(pathname, mode)) != NULL)
  1888.        {
  1889.           return(f);
  1890.        }
  1891.     }
  1892.     strcpy(pathname, file0);
  1893.     strcat(pathname, filename);
  1894.     if ((f = fopen(pathname, mode)) != NULL)
  1895.     {
  1896.       return(f);
  1897.     }
  1898.   }
  1899.  
  1900.   if (err_flag)
  1901.   {
  1902.     if (l1)
  1903.     {
  1904.       Error_Line("Could not find file '%s%s'\n",filename,ext1);
  1905.     }
  1906.     else
  1907.     {
  1908.       Error_Line("Could not find file '%s'\n",filename);
  1909.     }
  1910.   }
  1911.   
  1912.   return(NULL);
  1913. }
  1914.  
  1915. /*****************************************************************************
  1916. *
  1917. * FUNCTION
  1918. *
  1919. * INPUT
  1920. *   
  1921. * OUTPUT
  1922. *   
  1923. * RETURNS
  1924. *   
  1925. * AUTHOR
  1926. *   
  1927. * DESCRIPTION
  1928. *
  1929. * CHANGES
  1930. *
  1931. ******************************************************************************/
  1932.  
  1933. static int Has_Extension (name)
  1934. char *name;
  1935. {
  1936.    char *p;
  1937.  
  1938.    if (name!=NULL)
  1939.    {
  1940.      p=strrchr(name, '.');
  1941.  
  1942.      if (p!=NULL)
  1943.      {
  1944.         if ((strlen(name)-(p-name))<=4)
  1945.         {
  1946.            return (TRUE);
  1947.         }
  1948.      }
  1949.    }
  1950.    return (FALSE);
  1951. }
  1952.  
  1953.  
  1954. /*****************************************************************************
  1955. *
  1956. * FUNCTION
  1957. *
  1958. *   pov_shellout
  1959. *
  1960. * INPUT
  1961. *
  1962. *   template_command - the template command string to execute
  1963. *   
  1964. * OUTPUT
  1965. *
  1966. * RETURNS
  1967. *
  1968. * AUTHOR
  1969. *
  1970. *   POV-Ray Team
  1971. *
  1972. * DESCRIPTION
  1973. *
  1974. *   Execute the command line described by the string being passed in
  1975. *
  1976. * CHANGES
  1977. *
  1978. *   -
  1979. *
  1980. ******************************************************************************/
  1981.  
  1982. SHELLRET pov_shellout (Type)
  1983. SHELLTYPE Type;
  1984. {
  1985.   char real_command[POV_MAX_CMD_LENGTH];
  1986.   int i, j, l = 0;
  1987.   int length;
  1988.   SHELLRET Return_Code;
  1989.   char *s = NULL;
  1990.   char *template_command;
  1991.  
  1992.  
  1993.   if ( opts.Shellouts == NULL ) return(IGNORE_RET);
  1994.  
  1995.   template_command=opts.Shellouts[Type].Command;
  1996.  
  1997.   if ((length = strlen(template_command)) == 0)
  1998.   {
  1999.     return(IGNORE_RET);
  2000.   }
  2001.  
  2002.   switch(Type)
  2003.   {
  2004.     case PRE_SCENE_SHL:  s="pre-scene";   break;
  2005.     case PRE_FRAME_SHL:  s="pre-frame";   break;
  2006.     case POST_FRAME_SHL: s="post-frame";  break;
  2007.     case POST_SCENE_SHL: s="post-scene";  break;
  2008.     case USER_ABORT_SHL: s="user about";  break;
  2009.     case FATAL_SHL:      s="fatal error"; break;
  2010.     case MAX_SHL: /* To remove warnings*/ break;
  2011.   }
  2012.  
  2013.   Status_Info("\nPerforming %s shell-out command",s);
  2014.  
  2015.   /* First, find the real command */
  2016.  
  2017.   for (i = 0, j = 0; i < length; )
  2018.   {
  2019.     if (template_command[i] == '%')
  2020.     {
  2021.       switch (toupper(template_command[i+1]))
  2022.       {
  2023.          case 'O':
  2024.  
  2025.           strncpy(&real_command[j], opts.Output_Numbered_Name, 
  2026.                (unsigned)(l=strlen(opts.Output_Numbered_Name)));
  2027.  
  2028.           break;
  2029.  
  2030.          case 'P':
  2031.  
  2032.           strncpy(&real_command[j], opts.Output_Path,(unsigned)(l=strlen(opts.Output_Path)));
  2033.  
  2034.           break;
  2035.  
  2036.          case 'S':
  2037.  
  2038.           strncpy(&real_command[j], opts.Scene_Name, (unsigned)(l=strlen(opts.Scene_Name)));
  2039.  
  2040.           break;
  2041.  
  2042.          case 'N':
  2043.  
  2044.           sprintf(&real_command[j],"%d",opts.FrameSeq.FrameNumber);
  2045.           l = strlen(&real_command[j]);
  2046.  
  2047.           break;
  2048.  
  2049.          case 'K':
  2050.  
  2051.           sprintf(&real_command[j],"%f",opts.FrameSeq.Clock_Value);
  2052.           l = strlen(&real_command[j]);
  2053.  
  2054.           break;
  2055.  
  2056.          case 'H':
  2057.  
  2058.           sprintf(&real_command[j],"%d",Frame.Screen_Height);
  2059.           l = strlen(&real_command[j]);
  2060.  
  2061.           break;
  2062.  
  2063.          case 'W':
  2064.  
  2065.           sprintf(&real_command[j],"%d",Frame.Screen_Width);
  2066.           l = strlen(&real_command[j]);
  2067.  
  2068.           break;
  2069.  
  2070.          case '%':
  2071.  
  2072.           real_command[j]='%';
  2073.  
  2074.           l=1;
  2075.  
  2076.           break;
  2077.        }
  2078.  
  2079.        j+=l;
  2080.  
  2081.        i+=2; /* we used 2 characters of template_command */
  2082.     }
  2083.     else
  2084.     {
  2085.       real_command[j++]=template_command[i++];
  2086.     }
  2087.   }
  2088.  
  2089.   real_command[j]='\0';
  2090.  
  2091.   Return_Code=POV_SYSTEM(real_command);
  2092.  
  2093.   if (opts.Shellouts[Type].Inverse)
  2094.   {
  2095.     Return_Code=!Return_Code;
  2096.   }
  2097.  
  2098.   if (Return_Code)
  2099.   {
  2100.     if (Type < USER_ABORT_SHL)
  2101.     {
  2102.       switch(opts.Shellouts[Type].Ret)
  2103.       {
  2104.         case FATAL_RET:
  2105.  
  2106.           Error("Fatal error returned from shellout command.");
  2107.  
  2108.           break;
  2109.  
  2110.         case USER_RET:
  2111.  
  2112.           Check_User_Abort(TRUE); /* the TRUE forces user abort */
  2113.  
  2114.           break;
  2115.  
  2116.         case QUIT_RET:
  2117.  
  2118.           Terminate_POV(0);
  2119.  
  2120.           break;
  2121.  
  2122.         case IGNORE_RET:
  2123.         case SKIP_ONCE_RET:
  2124.         case ALL_SKIP_RET: /* Added to remove warnings */
  2125.           break;
  2126.       }
  2127.     }
  2128.  
  2129.     return(opts.Shellouts[Type].Ret);
  2130.   }
  2131.  
  2132.   return(IGNORE_RET);
  2133. }
  2134.  
  2135. /*****************************************************************************
  2136. *
  2137. * FUNCTION
  2138. *
  2139. * INPUT
  2140. *   
  2141. * OUTPUT
  2142. *   
  2143. * RETURNS
  2144. *
  2145. * AUTHOR
  2146. *
  2147. * DESCRIPTION
  2148. *
  2149. * CHANGES
  2150. *
  2151. ******************************************************************************/
  2152.  
  2153. static void init_shellouts()
  2154. {
  2155.   int i;
  2156.  
  2157.   opts.Shellouts=POV_MALLOC(sizeof(SHELLDATA)*MAX_SHL,"shellout data");
  2158.  
  2159.   for (i=0; i < MAX_SHL; i++)
  2160.   {
  2161.     opts.Shellouts[i].Ret=IGNORE_RET;
  2162.     opts.Shellouts[i].Inverse=FALSE;
  2163.     opts.Shellouts[i].Command[0]='\0';
  2164.   }
  2165. }
  2166.  
  2167. /*****************************************************************************
  2168. *
  2169. * FUNCTION
  2170. *
  2171. * INPUT
  2172. *
  2173. * OUTPUT
  2174. *
  2175. * RETURNS
  2176. *
  2177. * AUTHOR
  2178. *
  2179. * DESCRIPTION
  2180. *
  2181. * CHANGES
  2182. *
  2183. ******************************************************************************/
  2184.  
  2185. static void destroy_shellouts()
  2186. {
  2187.   if (opts.Shellouts != NULL)
  2188.   {
  2189.     POV_FREE(opts.Shellouts);
  2190.   }
  2191.  
  2192.   opts.Shellouts=NULL;
  2193. }
  2194.  
  2195.  
  2196. /*****************************************************************************
  2197. *
  2198. * FUNCTION
  2199. *
  2200. *   closest_power_of_2
  2201. *
  2202. * INPUT
  2203. *
  2204. *   theNumber - the value to determine closest power of 2 for.
  2205. *
  2206. * OUTPUT
  2207. *
  2208. * RETURNS
  2209. *
  2210. *   The closest power of two is returned, or zero if the
  2211. *   argument is less than or equal to zero.
  2212. *
  2213. * AUTHOR
  2214. *
  2215. *   Eduard Schwan
  2216. *
  2217. * DESCRIPTION
  2218. *
  2219. *   Decription: Find the highest positive power of 2 that is
  2220. *   less than or equal to the number passed.
  2221. *
  2222. *   Input  Output
  2223. *   -----  ------
  2224. *     0      0
  2225. *     1      1
  2226. *     2      2
  2227. *     3      2
  2228. *     8      8
  2229. *     9      8
  2230. *
  2231. * CHANGES
  2232. *
  2233. *   Aug 1994 : Created by Eduard.
  2234. *
  2235. ******************************************************************************/
  2236.  
  2237. static unsigned closest_power_of_2(theNumber)
  2238. unsigned theNumber;
  2239. {
  2240.   int PowerOf2Counter;
  2241.  
  2242.   /* do not handle zero or negative numbers for now */
  2243.  
  2244.   if (theNumber <= 0)
  2245.   {
  2246.     return(0);
  2247.   }
  2248.  
  2249.   /* count the number in question down as we count up a power of 2 */
  2250.  
  2251.   PowerOf2Counter = 1;
  2252.  
  2253.   while (theNumber > 1)
  2254.   {
  2255.     /* move our power of 2 counter bit up... */
  2256.  
  2257.     PowerOf2Counter <<= 1;
  2258.  
  2259.     /* and reduce our test number by a factor of 2 two */
  2260.  
  2261.     theNumber >>= 1;
  2262.   }
  2263.  
  2264.   return(PowerOf2Counter);
  2265. }
  2266.  
  2267. /*****************************************************************************
  2268. *
  2269. * FUNCTION
  2270. *
  2271. *   pre_init_povray
  2272. *
  2273. * INPUT -- none
  2274. *
  2275. * OUTPUT
  2276. *
  2277. * RETURNS
  2278. *
  2279. * AUTHOR -- CEY
  2280. *
  2281. * DESCRIPTION
  2282. *
  2283. *   This routine does essential initialization that is required before any
  2284. *   POV_MALLOC-like routines may be called and before any text streams
  2285. *   may be used.
  2286. *   
  2287. *   If you are using alt_main and need access to any part of the generic code
  2288. *   before alt_main is called, you MUST call this routine first!  Also note
  2289. *   that it is safe to call it twice.  If you don't call it, alt_main will.
  2290. *   It won't hurt if you both do it.
  2291. *   
  2292. *   NOTE: Terminate_POV de-initializes these features.  Therefore you may
  2293. *   need to call it again between sucessive calls to alt_main.  If you call
  2294. *   pre_init_povray but for some reason you abort and don't call alt_main,
  2295. *   then you should call Terminate_POV to clean up.
  2296. *
  2297. * CHANGES
  2298. *   Nov 1995 : Created by CEY
  2299. *
  2300. ******************************************************************************/
  2301.  
  2302. void pre_init_povray()
  2303. {
  2304.   if (pre_init_flag==1234)
  2305.   {
  2306.     return;
  2307.   }
  2308.       
  2309.   /* Initialize memory. */
  2310.   mem_init();
  2311.  
  2312.   /* Initialize streams. In USERIO.C */
  2313.   Init_Text_Streams();
  2314.  
  2315.   init_shellouts();
  2316.  
  2317.   pre_init_tokenizer ();
  2318.   
  2319.   pre_init_flag=1234;
  2320. }
  2321.  
  2322. void POV_Split_Path(s,p,f)
  2323. char *s;
  2324. char *p;
  2325. char *f;
  2326. {
  2327. char *l;
  2328.  
  2329.   strcpy(p,s);
  2330.  
  2331.   if ((l=strrchr(p,FILENAME_SEPARATOR))==NULL)
  2332.   {
  2333.      if ((l=strrchr(p,DRIVE_SEPARATOR))==NULL)
  2334.      {
  2335.         strcpy(f,s);
  2336.         p[0]='\0';
  2337.         return;
  2338.      }
  2339.   }
  2340.   
  2341.   l++;
  2342.   strcpy(f,l);
  2343.   *l='\0';
  2344.  
  2345. }
  2346.